package org.example.web.controller;

import org.example.config.RabbitMqConfiguration;
import org.example.web.dto.InspectDto;
import org.example.web.lib.Bridge;
import org.example.web.lib.MetaRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
public class TestController {
    final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Autowired
    ApplicationContext ctx;

    public void setEmpty() {
        this.ctx = null;
    }


    @RequestMapping({"/string"})
    public Integer string() {
        return Integer.valueOf("HELLO WORLD".hashCode());
    }


    @RequestMapping({"/"})
    public InspectDto home(HttpServletRequest request) {
        String name = request.getParameter("name");
        if (name == null) {
            name = "World";
        }
        InspectDto dto = new InspectDto();
        dto.setId(this.ctx.getId());
        dto.setParams(name);
        dto.setApplicationName(this.ctx.getApplicationName());
        dto.setControllerClass(getClass());
        dto.setController(this);
        dto.setCurrentTime(LocalDateTime.now());
        dto.setApplicationContext(this.ctx);
        dto.setApplicationContextClass(this.ctx.getClass());
        dto.setParentContext(this.ctx.getParent());
        dto.setBeanFactory(this.ctx.getAutowireCapableBeanFactory());
        dto.setParentContext(this.ctx.getParentBeanFactory());
        dto.setStartupDate(Long.valueOf(this.ctx.getStartupDate()));

        Bridge.put(getKey("inspect"), dto);
        Bridge.put(getKey("controller"), this);
        return dto;
    }


    private String getKey(String suffix) {
        return this.ctx.getApplicationName().replace("/", "").replace("-", "") + suffix;
    }


    @RequestMapping({"/counter"})
    public String counter() {
        return this.ctx.getApplicationName() + "$" + MetaRepository.increment();
    }


    @RequestMapping({"/inspect/{name}"})
    public Object inspect(@PathVariable("name") String name) {
        return Bridge.get(name);
    }


    @RequestMapping({"/destroy/{name}"})
    public String destroy(@PathVariable("name") String name) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Object obj = Bridge.get(name);
        Method method = obj.getClass().getMethod("setEmpty", new Class[0]);
        method.invoke(obj, new Object[0]);
        return name;
    }


    @RequestMapping({"/convert/{name}"})
    public InspectDto convert(@PathVariable("name") String name) {
        return (InspectDto) Bridge.get(name);
    }


    @RequestMapping({"/instanceof/{name}"})
    public Boolean instanceof1(@PathVariable("name") String name) {
        Object obj = Bridge.get(name);
        return Boolean.valueOf(obj instanceof InspectDto);
    }


    @RequestMapping({"/keys"})
    public List<String> keys() {
        return (List) Bridge.stream().map(entry -> (String) entry.getKey()).collect(Collectors.toList());
    }

    @Autowired
    RabbitMqConfiguration config;

    @RequestMapping("/mq")
    public Map<String, String> mqConfiguration() {
        Map<String, String> map = new HashMap<>();
        map.put("host", config.getHost());
        map.put("password", config.getPassword());
        map.put("port", config.getPort());
        map.put("username", config.getUsername());
        return map;
    }
}
